#!/usr/bin/python3
# -*- coding: utf-8 -*-
# ======================================#
# @Author   : duanqizhong
# @time     : 2021-1-2 23:20
# @file     : utils.py
# @Software : PyCharm
# ======================================#
import os
import re
import json
import time
import requests
import xmltodict
from lxml import etree
from collections import defaultdict
from config import DING_TOKEN_FOCUS, DING_TOKEN_AI, DING_TOKEN_TOP

from src.tools.ding import send_text


def get_year():
    return int(time.strftime("%Y", time.localtime()))


def xml_to_json(xml_str):
    json_parse = xmltodict.parse(xml_input=xml_str)
    return json_parse


def parse_fund_table_xml(content, nums, collect, title, print=False):
    root = etree.HTML(content)
    tbody = root.xpath("//div[@id='tableDiv']//table//tbody")
    code_list = []
    fund_info = []
    fund_field = []
    tag = True
    for tr in tbody[0].xpath(".//tr"):
        nums -= 1
        "序号，基金代码，基金简称，单位净值，累计净值，单位净值（昨天），累计净值（昨天），日增长值，日增长率，申购状态，赎回状态，手续费"
        td = tr.xpath(".//td//text()")
        code = td[1]
        fund_i = {
            "code": code,
            "name": td[2],
            "单位净值": td[-9],
            "累计净值": td[-8],
            "增长率": td[-4],
            "状态": td[-3],
            "费率": td[-1]
        }
        code_list.append((code, td[2]))
        collect[code] = fund_i.copy()
        fund_info.append(fund_i.copy())
        if tag:
            tag = 0
            fund_field = fund_i.keys()
        if nums == 0:
            break
    if print:
        text = "  ".join(fund_field) + "\n"
        for f in fund_info:
            text += "   ".join(f.values()) + "\n"
        send_text(title, text, DING_TOKEN_TOP)

    return code_list


def collect_gp_info(url, collect, year=get_year()):
    """获取基金页面股票占比信息"""
    if year < 2021: return {}
    url_gp = f"{url}&year={year}"
    result_gp = requests.get(url_gp)
    gp_info = defaultdict(dict)
    if result_gp.status_code == 200:
        root = etree.HTML(result_gp.content.decode("utf-8"))
        tbody = root.xpath("//tbody")
        if len(tbody):
            for tr in tbody[0].xpath(".//tr"):
                td = tr.xpath(".//td//text()")
                code = td[1]
                # top统计时，如果code存在，不在重复获取//*[@id="cwzbDataBox"]/tr[1]/td[6]
                if code in collect.keys():
                    continue
                gp_info[code] = {
                    # "num": td[0],
                    "code": td[1],
                    "name": td[2],
                    "占比": td[-3],
                    "持股": td[-2],
                    "持股市值": td[-1]
                }
                # 股票地址，为了具体获取股票信息
                try:
                    url = f'http:{tr.xpath(".//td[2]/a/@href")[0]}'
                except:
                    return gp_info
                stock_code = os.path.basename(url)
                # 股票上市地：sz:0 sh:1 hk:116
                # stock_market = stock_code[0:2]
                stock_market = stock_code.split(".")[0]
                if "hk" in url:
                    stock_market = "hk"

                # f43:最新价 f47:总手 f135:流入 f136:流出 f137:净流入 f168:换手率 f170:涨幅
                gp_info[code].update(get_stock_price_increate(stock_market, code))
                # 股票代码 股票名称 占净值比例 当前价 涨跌幅 换手率
                gp_info[code].update(get_stock_industry(url=url))
                collect[code] = gp_info[code].copy()
        else:
            year -= 1
            return collect_gp_info(url, collect, year)
    return gp_info


def get_stock_finance(code, market="HK"):
    """财报"""
    url = f"http://f10.eastmoney.com/NewFinanceAnalysis/DubangAnalysisAjax?code={market.upper()}{code}"
    data = requests.get(url).json()
    info = data["bgq"][0]


def collect_fund_info(content, collect):
    root = etree.HTML(content)
    try:
        month_one = root.xpath("//*[@id='body']/div[11]/div/div/div[3]/div[1]/div[1]/dl[1]/dd[2]/span[2]/text()")[0]
        month_three = root.xpath("//*[@id='body']/div[11]/div/div/div[3]/div[1]/div[1]/dl[2]/dd[2]/span[2]/text()")[0]
        month_six = root.xpath("//*[@id='body']/div[11]/div/div/div[3]/div[1]/div[1]/dl[3]/dd[2]/span[2]/text()")[0]
        year_one = root.xpath("//*[@id='body']/div[11]/div/div/div[3]/div[1]/div[1]/dl[1]/dd[3]/span[2]/text()")[0]
        year_three = root.xpath("//*[@id='body']/div[11]/div/div/div[3]/div[1]/div[1]/dl[2]/dd[3]/span[2]/text()")[0]
        begin_start = root.xpath("//*[@id='body']/div[11]/div/div/div[3]/div[1]/div[1]/dl[3]/dd[3]/span[2]/text()")[0]
        roi = root.xpath("//*[@id='body']/div[11]/div/div/div[3]/div[1]/div[1]/dl[2]/dd[1]/span[2]/text()")[0]
        # 最近增长率：一月，三月，六月，一年，三年，成立以来
        fund_info = {
            "roi": roi,
            "month_one": month_one,
            "month_three": month_three,
            "month_six": month_six,
            "year_one": year_one,
            "year_three": year_three,
            "begin_start": begin_start,
        }
        collect.update(fund_info)
        return fund_info
    except:
        pass
    return {}


def collect_zq_info(content, collect):
    """债券代码 债券名称 占净值比例 持仓市值"""
    root = etree.HTML(content)
    tbody = root.xpath("//tbody")
    zq_info = defaultdict(dict)
    if len(tbody):
        for tr in tbody[0].xpath(".//tr"):
            # url=tr.xpath(".//td[2]/a/@herf")[0]
            td = tr.xpath(".//td//text()")
            # 债券代码 债券名称 占净值比例 持仓市值
            code = td[1]
            if code not in collect.keys():
                zq_info[code] = {
                    "code": td[1],
                    "name": td[2],
                    "占比": td[3],
                    "市值": td[4]
                }
                collect[code] = zq_info[code].copy()
    return zq_info


def get_stock_price_increate(stock_type, code):
    """通过接口获取股票涨跌幅，流入流出"""
    stock = 116
    if stock_type in ("sh","1"):
        stock = 1
    elif stock_type in ("sz","0"):
        stock = 0

    def count_str(data, count=10000):
        try:
            return str(int(data / count))
        except:
            return "-"

    # result=requests.get(f"http://push2.eastmoney.com/api/qt/stock/get?ut=fa5fd1943c7b386f172d6893dbfba10b&invt=2&fltt=2&fields=f43,f57,f58,f169,f170,f46,f44,f51,f168,f47,f164,f163,f116,f60,f45,f52,f50,f48,f167,f117,f71,f161,f49,f530,f135,f136,f137,f138,f139,f141,f142,f144,f145,f147,f148,f140,f143,f146,f149,f55,f62,f162,f92,f173,f104,f105,f84,f85,f183,f184,f185,f186,f187,f188,f189,f190,f191,f192,f107,f111,f86,f177,f78,f110,f262,f263,f264,f267,f268,f250,f251,f252,f253,f254,f255,f256,f257,f258,f266,f269,f270,f271,f273,f274,f275,f127,f199,f128,f193,f196,f194,f195,f197,f80,f280,f281,f282,f284,f285,f286,f287,f292&secid={stock}.{code}")

    # f43:最新价 f47:总手 f135:流入 f136:流出 f137:净流入 f168:换手率 f170:涨幅
    push_url=f"http://push2.eastmoney.com/api/qt/stock/get?ut=fa5fd1943c7b386f172d6893dbfba10b&invt=2&fltt=2&fields=f43,f47,f135,f136,f137,f168,f170&secid={stock}.{code}"
    result = requests.get(push_url)
    gp_info = defaultdict(dict)
    if result.status_code == 200:
        data_dict = result.json().get("data", None)
        if data_dict:
            try:
                yxfd = f"{round(data_dict.get('f137') / ((data_dict.get('f47') / data_dict.get('f168')) * (data_dict.get('f43') * (1 - data_dict.get('f170') / 100))), 3)}%"
            except:
                yxfd = "-"
            gp_info = {
                "增率": f'{data_dict.get("f170")}%',
                "最新价": str(data_dict.get("f43")),
                "流入": count_str(data_dict.get("f135"), 1000000),
                "流出": count_str(data_dict.get("f136"), 1000000),
                "净流入": count_str(data_dict.get("f137"), 1000000),
                "总手": count_str(data_dict.get("f47"), 10000),
                "换手率": f'{data_dict.get("f168")}%',
                "影响幅度": yxfd
            }
    # 获取毛利，净利等
    gp_info.update(get_stock_info(code, stock=stock))
    return gp_info


def get_stock_info(code, stock=1):
    # 总市值 净资产 净利润 市盈率 市净率 毛利率 净利率 ROE
    timestamp = int(time.time() * 1000)
    url = f"http://push2.eastmoney.com/api/qt/slist/get?spt=1&np=3&fltt=2&invt=2&fields=f20,f135,f45,f9,f23,f49,f129,f37&ut=bd1d9ddb04089700cf9c27f6f7426281&cb=jQuery11240585262503951258_{timestamp}&secid={stock}.{code}&_={timestamp}"
    result = requests.get(url)
    gp_info = defaultdict(dict)
    if result.status_code == 200:
        re_pattern = re.compile(r"\({(.*?)}\);")
        stock_info_str = "{" + re_pattern.findall(result.text)[0] + "}"
        data_dict = json.loads(stock_info_str)
        try:
            data = data_dict["data"]["diff"][0]
            gp_info = {
                "总资产": str(int(data.get("f20") / 1000000)),
                "净资产": str(int(data.get("f135") / 1000000)),
                "净利润": str(int(data.get("f45") / 1000000)),
                "市盈率": f"{round(data.get('f9'), 2)}%",
                "毛利率": f"{round(data.get('f49'), 2)}%",
                "净利率": f"{round(data.get('f129'), 2)}%",
                "ROE": f"{round(data.get('f37'), 2)}%",
            }

            if stock == 116:
                gp_info.update({
                    "市盈率": f"{round(data.get('115'), 2)}%",
                    "市净率": f"{round(data.get('f23'), 2)}%",
                    "市现率": f"{round(data.get('f131'), 2)}%",
                    "市销率": f"{round(data.get('f130'), 2)}%",
                })
        except:
            gp_info = {"总资产": "-", "净资产": "-", "净利润": "-", "市盈率": "-", "毛利率": "-", "净利率": "-", "ROE": "-", }
    return gp_info


def get_stock_industry(url):
    """获取股票信息"""
    result = requests.get(url)
    gp_info = {"industry": "其它"}
    if result.status_code == 200:
        content = result.content.decode("utf-8")
        root = etree.HTML(content)
        industrys = root.xpath("/html/body/div[9]/div/div[1]/a[3]/text()")
        if len(industrys):
            gp_info["industry"] = industrys[0]
    return gp_info


def print_fund_info(code, name, fund, gp, zq):
    """输出基金详细信息：gp,zq"""
    if name:
        title = f"{code}:{name} {'  '.join(list(fund.values()))}"
    else:
        title = f"{code}: {'  '.join(list(fund.values()))}"
    content = ""
    if gp:
        content += "【股票】\n"
        tag = True
        for g, info in gp.items():
            industry = info.pop("industry")
            if tag:
                tag = False
                content += '  '.join(info.keys()) + "\n"
            content += "[" + industry + "]" + '  '.join(info.values()) + "\n"
    if zq:
        content += "【债券】\n"
        tag = True
        for z, info in zq.items():
            if tag:
                tag = False
                content += '  '.join(info.keys()) + "\n"
            content += "  ".join(zq.values())
    send_text(title, content, DING_TOKEN_FOCUS)


def print_classify_detail(collect, gp=True, zq=False):
    """
    分类输出实例内收集的信息
    :param collect: 收集股票，基金，债券信息
    :param gp: 是否输出gp详情
    :param zq: 是否输出债券详情
    :return:
    """
    fund_field = []
    fund = []
    gp_field = []
    gp = defaultdict(list)
    zq_field = []
    zq = []
    for type, info in collect.items():
        if type == "Fund":
            tag = 0
            for code, fi in info.items():
                if tag == 0:
                    tag = 1
                    fund_field = list(fi.keys())
                fund.append(list(fi.values()))
        elif type == "GP":
            tag = 0
            for code, gi in info.items():
                industry = gi.pop("industry")
                code = gi.pop('code')
                name = gi.pop('name')
                gi.pop("占比")
                gi.pop("持股")
                gi.pop("持股市值")
                if tag == 0:
                    tag = 1
                    gp_field = ["code"] + list(gi.keys()) + ["name"]
                gp[industry].append(f"[{code}]  {'  '.join(gi.values())}  {name}")

        elif type == "ZQ":
            tag = 0
            for code, info in info.items():
                if tag == 0:
                    tag = 1
                    zq_field = list(info.keys())
                zq.append(list(info.values()))

    content = "  ".join(gp_field) + "\n"
    for industry, values in gp.items():
        if len(values)<5:
            continue
        title = f"top基金-{industry}"
        content = "  ".join(gp_field) + "\n"
        content += "\n".join(values)
        send_text(title, content, DING_TOKEN_AI)
        time.sleep(6)

    # send_text("top基金GP及分类", text, DING_TOKEN_AI)
    # send_text("top基金ZQ", "  ".join(set(collect_zq)), DING_TOKEN_AI)


def out_fund_all_up(all_dict, rate=5, count=50):
    infos_36 = defaultdict(dict)
    infos_24 = defaultdict(dict)
    infos_12 = defaultdict(dict)
    infos_other = defaultdict(dict)
    for key, values in all_dict.items():
        for value in values:
            if value > rate:
                l = len(values)
                if l == 7:
                    infos_36[key] = values
                elif l == 6:
                    infos_24[key] = values
                elif l == 5:
                    infos_12[key] = values
                else:
                    infos_other[key] = values
                break
    out_put_classify_info(infos_36, month=36)
    out_put_classify_info(infos_24, month=24)
    out_put_classify_info(infos_12, month=12)
    out_put_classify_info(infos_other, month=6)


def out_put_classify_info(dict_info, month=36):
    classify = defaultdict(list)
    for key, value in dict_info.items():
        sum_rate = round(sum(value), 2)
        content = f"{key} {value} sum={sum_rate}"
        if sum_rate > 150:
            classify[150].append(content)
        elif sum_rate > 120:
            classify[120].append(content)
        elif sum_rate > 90:
            classify[90].append(content)
        elif sum_rate > 70:
            classify[70].append(content)
        elif sum_rate > 50:
            classify[50].append(content)
        elif sum_rate > 30:
            classify[30].append(content)
        elif sum_rate > 10:
            classify[10].append(content)
        else:
            classify[0].append(content)

    title = f"【近{month}月各阶段全涨基】"
    for rate, fund_list in classify.items():
        content = "1周 1月 1-3月 3-6月 6-12月 12-24月 24-36月\n"
        content += "\n".join(fund_list)
        send_text(f"{title}{rate}", content, DING_TOKEN_AI)
        time.sleep(6)


def out_fund_down_down_up(dict_info, index_start=3, index_end=4):
    """最近在跌，但是历史再涨，历史涨小于现在跌"""
    infos = defaultdict(list)
    for key, values in dict_info.items():
        tag = False
        for i, v in enumerate(values):
            if v > 0 and i < index_start:
                tag = True
                break
        if tag: continue

        infos[key] = values

    title = f"【连跌3月以上】"
    content = "1周 1月 1-3月 3-6月 6-12月 12-24月 24-36月\n"
    for key, value in infos.items():
        content += f"{key} {value} sum={round(sum(value), 2)}\n"
    send_text(title, content, DING_TOKEN_FOCUS)
